package style.Leetcode.初级算法.str.str_20220804_3_验证回文串;

import org.apache.commons.lang3.StringUtils;

/**
 * 验证回文串
 * <p>
 * 给定一个字符串，验证它是否是回文串，只考虑字母和数字字符，可以忽略字母的大小写。
 * <p>
 * 说明：本题中，我们将空字符串定义为有效的回文串。
 * <p>
 * 示例 1:
 * <p>
 * 输入: "A man, a plan, a canal: Panama"
 * 输出: true
 * 解释："amanaplanacanalpanama" 是回文串
 * 示例 2:
 * <p>
 * 输入: "race a car"
 * 输出: false
 * 解释："raceacar" 不是回文串
 */
public class Solution {
    /**
     * 思路一：双指针法
     */
    public boolean isPalindrome1(String s) {
        if (StringUtils.isBlank(s)) return true;
        int left = 0, right = s.length() - 1;
        while (left < right) {
            // 过滤非数字、字母
            while (left < right && !Character.isLetterOrDigit(s.charAt(left))) {
                left++;
            }
            while (left < right && !Character.isLetterOrDigit(s.charAt(right))) {
                right--;
            }
            if (Character.toLowerCase(s.charAt(left)) != Character.toLowerCase(s.charAt(right))) {
                return false;
            }
            left++;
            right--;
        }
        return true;
    }

    /**
     * 思路二：正则匹配法
     */
    public boolean isPalindrome2(String s) {
        String s1 = s.replaceAll("[^A-Za-z0-9]", "").toUpperCase();
        String s2 = new StringBuffer(s1).reverse().toString();
        return s1.equals(s2);
    }

    /**
     * 思路三：递归法
     */
    public boolean isPalindrome3(String s) {
        if (StringUtils.isBlank(s)) return true;
        return isPalindromeHelper(s, 0, s.length() - 1);
    }

    private boolean isPalindromeHelper(String s, int left, int right) {
        if (left >= right) return true;
        while (left < right && !Character.isLetterOrDigit(s.charAt(left))) {
            left++;
        }
        while (left < right && !Character.isLetterOrDigit(s.charAt(right))) {
            right--;
        }
        return (Character.toLowerCase(s.charAt(left)) == Character.toLowerCase(s.charAt(right))) && isPalindromeHelper(s, ++left, --right);
    }

    public static void main(String[] args) {
        Solution solution = new Solution();
        System.out.println(solution.isPalindrome1("A man, a plan, a canal: Panama"));
        System.out.println(solution.isPalindrome2("A man, a plan, a canal: Panama"));
        System.out.println(solution.isPalindrome3("A man, a plan, a canal: Panama"));
    }
}
